package com.ruoyi.web.service;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import com.ruoyi.core.entity.BaseMap;
import com.ruoyi.core.entity.PageInfo;
import com.ruoyi.core.entity.SortInfo;
import com.ruoyi.core.entity.SumInfo;
import com.ruoyi.web.entity.db.Creator;
import com.ruoyi.web.entity.db.QueryCreator;
import com.ruoyi.web.entity.db.QueryPageCreator;
import com.ruoyi.web.entity.db.UpdateCreator;
import com.ruoyi.web.mapper.BaseMapperPlus;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

public interface IBaseService<M extends BaseMapperPlus<T, V>, T, V> {

    BaseMapperPlus<T, V> getBaseMapper();


    //===============增/删/改==============

    /**
     * 插入一条记录（选择字段，策略插入）
     *
     * @param entity 实体对象
     */
    default boolean save(T entity) {
        return SqlHelper.retBool(getBaseMapper().insert(entity));
    }

    /**
     * 根据 ID 选择修改
     *
     * @param entity 实体对象
     */
    default boolean updateById(T entity) {
        return SqlHelper.retBool(getBaseMapper().updateById(entity));
    }

    /**
     * 根据 whereEntity 条件，更新记录
     *
     * @param updateWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper}
     */
    default boolean update(Wrapper<T> updateWrapper) {
        return SqlHelper.retBool(getBaseMapper().update(null, updateWrapper));
    }

    /**
     * TableId 注解存在更新记录，否插入一条记录
     *
     * @param entity 实体对象
     */
    default boolean saveOrUpdate(T entity) {
        return getBaseMapper().insertOrUpdate(entity);
    }

    /**
     * 根据实体(ID)删除
     *
     * @param entity 实体
     * @since 3.4.4
     */
    default boolean removeById(T entity) {
        return SqlHelper.retBool(getBaseMapper().deleteById(entity));
    }

    /**
     * 根据ID删除
     *
     * @param id ID
     */
    default boolean removeById(Serializable id) {
        return SqlHelper.retBool(getBaseMapper().deleteById(id));
    }

    /**
     * 根据 entity 条件，删除记录
     *
     * @param queryWrapper 实体包装类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
     */
    default boolean remove(Wrapper<T> queryWrapper) {
        return SqlHelper.retBool(getBaseMapper().delete(queryWrapper));
    }

    /**
     * 根据 columnMap 条件，删除记录
     *
     * @param columnMap 表字段 map 对象
     */
    default boolean removeByMap(Map<String, Object> columnMap) {
        Assert.notEmpty(columnMap, "error: columnMap must not be empty");
        return SqlHelper.retBool(getBaseMapper().deleteByMap(columnMap));
    }


    //===============批量增/批量改==============

    /**
     * 批量插入
     */
    default boolean saveBatch(Collection<T> entityList) {
        return getBaseMapper().insertBatch(entityList);
    }

    /**
     * 批量插入(包含限制条数)
     */
    default boolean saveBatch(Collection<T> entityList, int batchSize) {
        return getBaseMapper().insertBatch(entityList, batchSize);
    }

    /**
     * 批量更新
     */
    default boolean updateBatchById(Collection<T> entityList) {
        return getBaseMapper().updateBatchById(entityList);
    }

    /**
     * 批量更新(包含限制条数)
     */
    default boolean updateBatchById(Collection<T> entityList, int batchSize) {
        return getBaseMapper().updateBatchById(entityList, batchSize);
    }

    /**
     * 批量插入或更新
     */
    default boolean saveOrUpdateBatch(Collection<T> entityList) {
        return getBaseMapper().insertOrUpdateBatch(entityList);
    }

    /**
     * 批量插入或更新(包含限制条数)
     */
    default boolean saveOrUpdateBatch(Collection<T> entityList, int batchSize) {
        return getBaseMapper().insertOrUpdateBatch(entityList, batchSize);
    }


    //===============单笔查询==============

    /**
     * 根据 ID 查询
     *
     * @param id 主键ID
     */
    default V getById(String id) {
        return getBaseMapper().selectVoById(id);
    }

    /**
     * 根据 ID 查询
     */
    default V getById(T entity) {
        return getBaseMapper().selectVoById(entity);
    }

    /**
     * 根据 Wrapper，查询一条记录 <br/>
     * <p>结果集，如果是多个会抛出异常，随机取一条加上限制条件 wrapper.last("LIMIT 1")</p>
     *
     * @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
     */
    default V getOne(Wrapper<T> queryWrapper) {
        return getBaseMapper().selectVoOne(queryWrapper);
    }

    /**
     * 根据 Map，查询一条记录 <br/>
     * <p>结果集，如果是多个会抛出异常，随机取一条加上限制条件 wrapper.last("LIMIT 1")</p>
     */
    default V getOneByMap(Map<String, Object> map) {
        return getBaseMapper().selectVoOneByMap(map);
    }


    //===============列表查询==============

    /**
     * 查询所有
     *
     * @see Wrappers#emptyWrapper()
     */
    default List<V> list() {
        return getBaseMapper().selectVoList();
    }

    /**
     * 查询所有
     *
     * @see Wrappers#emptyWrapper()
     */
    default List<V> list(Wrapper<T> wrapper) {
        return getBaseMapper().selectVoList(wrapper);
    }

    /**
     * 查询列表
     */
    default List<V> listByMap(Map<String, Object> map) {
        return getBaseMapper().selectVoByMap(map);
    }


    //===============分页查询==============

    /**
     * 分页查询单表数据
     */
    default List<V> list(int pageNum, int pageSize) {
        IPage<T> page1 = new Page<>(pageNum, pageSize);
        return list(page1);
    }

    /**
     * 分页查询单表数据
     *
     * @param page 分页条件
     * @return 列表数据
     * @since 3.5.3.2
     */
    default List<V> list(IPage<T> page) {
        return getBaseMapper().selectVoPageList(page);
    }

    /**
     * 分页查询单表数据
     *
     * @param page         分页条件
     * @param queryWrapper queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
     * @return 列表数据
     * @since 3.5.3.2
     */
    default List<V> list(IPage<T> page, Wrapper<T> queryWrapper) {
        return getBaseMapper().selectVoPageList(page, queryWrapper);
    }

    /**
     * 分页查询单表数据
     *
     * @param page 分页条件
     */
    default List<V> listByMap(IPage<T> page, Map<String, Object> map) {
        return getBaseMapper().selectVoPageList(page, map);
    }

    /**
     * 分页查询单表数据
     */
    default IPage<V> page(int pageNum, int pageSize) {
        IPage<T> page1 = new Page<>(pageNum, pageSize);
        return page(page1);
    }

    /**
     * 分页查询单表数据
     *
     * @param page 分页条件
     * @return 列表数据
     * @since 3.5.3.2
     */
    default IPage<V> page(IPage<T> page) {
        return getBaseMapper().selectVoPage(page);
    }

    /**
     * 分页查询单表数据
     *
     * @param page         分页条件
     * @param queryWrapper queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
     * @return 列表数据
     * @since 3.5.3.2
     */
    default IPage<V> page(IPage<T> page, Wrapper<T> queryWrapper) {
        return getBaseMapper().selectVoPage(page, queryWrapper);
    }

    /**
     * 分页查询单表数据
     *
     * @param page 分页条件
     * @return 列表数据
     * @since 3.5.3.2
     */
    default IPage<V> pageByMap(IPage<T> page, Map<String, Object> map) {
        return getBaseMapper().selectVoPage(page, map);
    }


    //===============自定义where==============

    /**
     * 根据 Creator，查询一条记录 <br/>
     * <p>结果集，如果是多个会抛出异常，随机取一条加上限制条件 wrapper.last("LIMIT 1")</p>
     */
    default V getOne(Creator queryCreator) {
        QueryWrapper<T> qw = Wrappers.query();
        Creator.toWrapper(qw, queryCreator.getWhere(), queryCreator.getQueryData());
        if (queryCreator instanceof QueryCreator) {
            QueryCreator.orderBy(qw, ((QueryCreator) queryCreator).getSorts());
        }
        return this.getOne(qw);
    }

    /**
     * 查询所有
     *
     * @see Wrappers#emptyWrapper()
     */
    default List<V> list(Creator queryCreator) {
        QueryWrapper<T> qw = Wrappers.query();
        Creator.toWrapper(qw, queryCreator.getWhere(), queryCreator.getQueryData());
        if (queryCreator instanceof QueryCreator) {
            QueryCreator.orderBy(qw, ((QueryCreator) queryCreator).getSorts());
        }
        return this.list(qw);
    }

    /**
     * 分页查询单表数据
     */
    default List<V> list(QueryPageCreator queryPageCreator) {
        QueryWrapper<T> qw = Wrappers.query();
        Creator.toWrapper(qw, queryPageCreator.getWhere(), queryPageCreator.getQueryData());
        QueryCreator.orderBy(qw, queryPageCreator.getSorts());
        IPage<T> page1 = new Page<>(queryPageCreator.getPageNum(), queryPageCreator.getPageSize());
        return this.list(page1, qw);
    }

    /**
     * 分页查询单表数据
     */
    default PageInfo<V> page(QueryPageCreator queryPageCreator) {
        QueryWrapper<T> qw = Wrappers.query();
        Creator.toWrapper(qw, queryPageCreator.getWhere(), queryPageCreator.getQueryData());
        List<SortInfo> sorts = null;

        //排序
        sorts = queryPageCreator.getSorts();
        if (sorts != null && sorts.size() > 0) {
            QueryCreator.orderBy(qw, sorts);
        }

        //合计行
        BaseMap summaryData = new BaseMap();
        List<SumInfo> sums = queryPageCreator.getSums();
        if (sums != null && sums.size() > 0) {
            QueryWrapper<T> qw1 = Wrappers.query();
            Creator.toWrapper(qw1, queryPageCreator.getWhere(), queryPageCreator.getQueryData());
            List<String> sumColumns = new ArrayList<>();
            for (SumInfo sum : sums) {
                sumColumns.add("" + sum.getSumType().toString() + "(" + Creator.resolveColumnName(sum.getSumName()) + ") as " + sum.getSumName());
            }
            qw1.select(sumColumns);
            List<Map<String, Object>> sum1 = getBaseMapper().selectMaps(qw1);
            if (sum1 != null && sum1.size() > 0) {
                summaryData = new BaseMap(sum1.get(0));
            }
        }


        IPage<T> page1 = new Page<>(queryPageCreator.getPageNum(), queryPageCreator.getPageSize());
        IPage<V> page2 = this.page(page1, qw);
        PageInfo<V> page3 = new PageInfo<>((int) page2.getCurrent(), (int) page2.getSize(), page2.getRecords(), (int) page2.getTotal());
        if (sorts != null && sorts.size() > 0) {
            SortInfo sortInfo = sorts.get(0);
            page3.setSortBy(sortInfo.getSortBy().toString());
            page3.setSortName(sortInfo.getSortName());
        }

        //合计行
        page3.setSummary(summaryData);

        return page3;

    }


    //删除/修改

    /**
     * 根据 queryCreator 条件，删除记录
     */
    default boolean remove(Creator queryCreator) {
        QueryWrapper<T> qw = Wrappers.query();
        Creator.toWrapper(qw, queryCreator.getWhere(), queryCreator.getQueryData());
        return this.remove(qw);
    }

    /**
     * 根据 whereEntity 条件，更新记录
     */
    default boolean update(Creator updateCreator) {
        UpdateWrapper<T> uw = Wrappers.update();
        Creator.toWrapper(uw, updateCreator.getWhere(), updateCreator.getQueryData());
        if (updateCreator instanceof UpdateCreator) {
            UpdateCreator.set(uw, ((UpdateCreator) updateCreator).getColumns());
        }
        return update(uw);
    }


}
